package com.k8.serialize;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianFactory;
import com.k8.common.factroy.BeanInitialize;
import com.k8.rpc.invoke.invocation.Invocation;
import com.k8.rpc.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.util.ReferenceCountUtil;

import java.io.IOException;

/**
 * @Author: k8
 * @CreateTime: 2025-03-27
 * @Version: 1.0
 * 对于某些request的byteBuf来说是会自动释放的
 * 但是对于alloc的ByteBuf可能不会得到释放
 */
public class DefaultHessian2Serializer implements BeanInitialize, Serializer {
    private HessianFactory hessianFactory;
    private static String SERIALIZER_NAME = "hessian2";

    @Override
    public String serializerName() {
        return SERIALIZER_NAME;
    }

    @Override
    public <T> T decode(ByteBuf byteBuf, Class<T> clazz) {
        try (ByteBufInputStream byteBufInputStream = new ByteBufInputStream(byteBuf)) {
            Hessian2Input hessian2Input = this.hessianFactory.createHessian2Input(byteBufInputStream);
            return clazz.cast(hessian2Input.readObject());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //对于传进来的ByteBuf，不进行释放
    @Override
    public <T> ByteBuf encode(T object, ByteBuf byteBuf) {
        try (ByteBufOutputStream byteBufOutputStream = new ByteBufOutputStream(byteBuf)) {
            Hessian2Output hessian2Output = this.hessianFactory.createHessian2Output(byteBufOutputStream);
            hessian2Output.writeObject(object);
            hessian2Output.flush();
            return byteBuf;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> ByteBuf encode(T object) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
        try (ByteBufOutputStream byteBufOutputStream = new ByteBufOutputStream(byteBuf)) {
            Hessian2Output hessian2Output = this.hessianFactory.createHessian2Output(byteBufOutputStream);
            hessian2Output.writeObject(object);
            hessian2Output.flush();
            return byteBuf;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public void initialize() {
        this.hessianFactory = new HessianFactory();
    }
}
